package me.boot.gen.code;

import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.engine.VelocityTemplateEngine;
import me.base.commom.model.dto.BaseEntityDTO;
import me.boot.common.constant.DbConst;
import me.boot.db.mybatis.template.SuperMapper;
import me.boot.db.mybatis.template.SuperService;
import me.boot.db.mybatis.template.entity.AutoEntity;
import me.boot.db.mybatis.template.impl.SuperServiceImpl;
import me.boot.web.common.template.impl.SuperControllerImpl;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;

import java.util.Collections;

/**
 * @Description:
 * @author: Sylar
 * @date: 2021年10月09日 11:40 下午
 */
@Component
@ConditionalOnProperty(value = "spring.datasource.url", matchIfMissing = true)
public class CodeGenerator {

    public static void generateCode(String author, String packageName, String moduleName, String projectDir) {
        CodeGenerator generator = SpringUtil.getBean(CodeGenerator.class);
        generator.genAuto(author, packageName, moduleName, projectDir);
    }

    final String AUTHOR_NAME = "Author";
    final String PACKAGE_NAME = "com.xxx.app";
    final String MODULE_NAME = "module";
    final String OUTPOUT_DIR = System.getProperty("os.name").toLowerCase().contains("windows") ? "D:/tmp/generatedCode" : "/tmp/generatedCode";

    final String[] SUPER_ENTITY_COLUMNS = new String[]{
            DbConst.COLUMN_ID,
            DbConst.COLUMN_CREATER,
            DbConst.COLUMN_UPDATER,
            DbConst.COLUMN_OWNER,
            DbConst.COLUMN_VERSION,
            DbConst.COLUMN_DELETED,
            DbConst.COLUMN_INVALID,
            DbConst.COLUMN_EXTRA};

    final String[] SUPER_DTO_COLUMNS = new String[]{
            DbConst.COLUMN_ID,
            DbConst.COLUMN_CREATER,
            DbConst.COLUMN_UPDATER,
            DbConst.COLUMN_OWNER,
            DbConst.COLUMN_VERSION,
            DbConst.COLUMN_DELETED,
            DbConst.COLUMN_INVALID,
            DbConst.COLUMN_EXTRA};

    @Value("${spring.datasource.url}")
    String url;

    @Value("${spring.datasource.username}")
    String username;

    @Value("${spring.datasource.password}")
    String password;

    public void genAuto() {
        genAuto(AUTHOR_NAME, PACKAGE_NAME, MODULE_NAME, OUTPOUT_DIR);
    }

    public void genAuto(String author, String packageName, String moduleName, String projectPath) {
        String codePath = StrUtil.format("{}/src/main/java", projectPath);
        String xmlPath = StrUtil.format("{}/src/main/resources/mapper", projectPath);

        DataSourceConfig.Builder dataSourceConfig = new DataSourceConfig.Builder(url, username, password);
        FastAutoGenerator
                .create(dataSourceConfig)
                .globalConfig(builder -> {
                    builder
                            .fileOverride()
                            .outputDir(codePath)
                            .author(author)
                            .enableSwagger()
                            .dateType(DateType.TIME_PACK)
                            .commentDate("yyyy-MM-dd");
                })
                .packageConfig(builder -> {
                    builder
                            .parent(packageName)
                            .moduleName(moduleName)
                            .pathInfo(Collections.singletonMap(OutputFile.mapperXml, xmlPath));
                })
                //模板引擎三选一即可
                .templateEngine(new VelocityTemplateEngine())
//                .templateEngine(new BeetlTemplateEngine())
//                .templateEngine(new FreemarkerTemplateEngine())
                .templateConfig(builder -> {
                    //自定义模板
//                    builder.controller("/templates/controller.java.vm");
//                    builder.disable(TemplateType.ENTITY);
                })
                .strategyConfig(builder -> {
                    builder
                            .entityBuilder()
                            .superClass(AutoEntity.class)
                            .addSuperEntityColumns(SUPER_ENTITY_COLUMNS)
                            .disableSerialVersionUID()
                            .enableLombok()
                            .enableColumnConstant()
                            .enableTableFieldAnnotation()
                            // entityBuilder  END
                            .dtoBuilder()
                            .superClass(BaseEntityDTO.class)
                            .addSuperEntityColumns(SUPER_DTO_COLUMNS)
                            .formatDtoFileName("%sDTO")
                            .enableLombok()
                            // dtoBuilder  END
                            .mapperBuilder()
                            .superClass(SuperMapper.class)
//                            .enableMapperAnnotation()
//                            .enableBaseResultMap()
//                            .enableBaseColumnList()
                            .formatMapperFileName("%sMapper")
                            // mapperBuilder  END
                            .serviceBuilder()
                            .superServiceClass(SuperService.class)
                            .superServiceImplClass(SuperServiceImpl.class)
                            .formatServiceFileName("%sService")
                            .formatServiceImplFileName("%sServiceImpl")
                            // serviceBuilder  END
                            .controllerBuilder()
                            .superClass(SuperControllerImpl.class)
                            .enableHyphenStyle()
                            .enableRestStyle()
                            .formatFileName("%sController");
                    // controllerBuilder  END
                })
                .injectionConfig(builder -> {
                    builder.beforeOutputFile((tableInfo, objectMap) -> {
                        System.out.println("tableInfo: " + tableInfo.getEntityName() + " objectMap: " + objectMap.size());
                    });
                })
                .execute();
    }

}
